#include "BinaryProtocolGenerator.h"
#include <QDebug>
#include <QDataStream>

/**
 * @brief 构造函数
 * @param parent 父对象
 */
BinaryProtocolGenerator::BinaryProtocolGenerator(QObject *parent)
    : QObject(parent)
{
}

/**
 * @brief 生成二进制协议命令
 * @param protocolConfig 协议配置
 * @param params 命令参数
 * @param customConfig 自定义配置
 * @return 生成的二进制命令
 */
QByteArray BinaryProtocolGenerator::generateCommand(const QVariantMap &protocolConfig, const QVariantMap &params)
{
    QVariantMap config = protocolConfig;

    // 使用配置或默认值
    int checksumType = config.value("checksumType", 0).toInt(); // 0: 求和校验, 1: CRC16, 2: 位级别异或
    bool addCRLF = config.value("addCRLF", true).toBool();

    // 1. 根据配置生成完整协议
    QByteArray fullCommand = generateProtocolFromConfig(params, config);
    if (fullCommand.isEmpty()) {
        qWarning() << "Failed to generate command: missing required parameters";
        return QByteArray();
    }

    // 2. 计算并添加校验和
    // 查找校验和字段
    QVariantList structure = config.value("structure").toList();
    int checksumOffset = -1;
    int checksumLength = 0;
    bool hasChecksum = false;

    for (const QVariant &field : structure) {
        QVariantMap fieldMap = field.toMap();
        if (fieldMap.value("calculated", false).toBool() && fieldMap.value("field").toString() == "checksum") {
            checksumOffset = fieldMap.value("byteOffset").toInt();
            checksumLength = fieldMap.value("length").toInt();
            hasChecksum = true;
            break;
        }
    }

    if (hasChecksum && checksumOffset >= 0 && checksumLength > 0) {
        // 计算校验和（不包含校验和字段本身）
        QByteArray dataToChecksum = fullCommand.left(checksumOffset);
        quint16 checksum = calculateChecksum(dataToChecksum, checksumType);

        // 将校验和写入到指定位置
        QDataStream checksumStream(&fullCommand, QIODevice::WriteOnly);
        checksumStream.device()->seek(checksumOffset);
        if (checksumLength == 1) {
            checksumStream << static_cast<quint8>(checksum & 0xFF);
        } else if (checksumLength == 2) {
            checksumStream << checksum;
        }
    }

    // 3. 添加帧结束符
    if (addCRLF) {
        fullCommand.append(0x0D); // CR
        fullCommand.append(0x0A); // LF
    }

    qDebug() << "Generated binary command:" << fullCommand.toHex();
    return fullCommand;
}

/**
 * @brief 从配置生成协议
 * @param params 命令参数
 * @param config 协议配置
 * @return 生成的协议数据
 */
QByteArray BinaryProtocolGenerator::generateProtocolFromConfig(const QVariantMap &params, const QVariantMap &config)
{
    // 获取协议结构
    QVariantList structure = config.value("structure").toList();
    if (structure.isEmpty()) {
        qWarning() << "Protocol structure is empty";
        return QByteArray();
    }

    // 确定协议总长度
    int maxOffset = 0;
    for (const QVariant &field : structure) {
        QVariantMap fieldMap = field.toMap();
        int offset = fieldMap.value("byteOffset").toInt();
        int length = fieldMap.value("length").toInt();
        maxOffset = qMax(maxOffset, offset + length);
    }

    QByteArray protocol(maxOffset, 0); // 预分配空间
    QDataStream stream(&protocol, QIODevice::WriteOnly);

    // 设置字节序
    bool littleEndian = config.value("littleEndian", true).toBool();
    if (!littleEndian) {
        stream.setByteOrder(QDataStream::BigEndian);
    }

    // 处理所有字段
    QMap<QString, bool> paramUsed;
    for (const QVariant &field : structure) {
        QVariantMap fieldMap = field.toMap();
        QString fieldName = fieldMap.value("field").toString();
        int byteOffset = fieldMap.value("byteOffset").toInt();
        int length = fieldMap.value("length").toInt();
        bool isConstant = fieldMap.value("constant", false).toBool();
        bool isCalculated = fieldMap.value("calculated", false).toBool();
        bool isVariable = fieldMap.value("variable", false).toBool();

        // 跳过计算字段（如校验和），后面单独处理
        if (isCalculated) {
            continue;
        }

        // 定位到字段位置
        stream.device()->seek(byteOffset);

        if (isConstant) {
            // 常量字段
            QVariant value = fieldMap.value("value");
            writeValueToStream(stream, value, length);
        } else if (isVariable) {
            // 变量字段
            if (!params.contains(fieldName)) {
                qWarning() << "Missing required parameter:" << fieldName;
                return QByteArray();
            }
            QVariant value = params.value(fieldName);
            writeValueToStream(stream, value, length);
            paramUsed[fieldName] = true;
        } else if (fieldMap.contains("bitFields")) {
            // 位字段
            QVariantMap bitFields = fieldMap.value("bitFields").toMap();
            quint8 byteValue = 0;

            for (auto it = bitFields.begin(); it != bitFields.end(); ++it) {
                QString bitFieldName = it.key();
                QVariantMap bitFieldConfig = it.value().toMap();
                int bitOffset = bitFieldConfig.value("bitOffset").toInt();
                int bitWidth = bitFieldConfig.value("bits").toInt();

                if (params.contains(bitFieldName)) {
                    int value = params.value(bitFieldName).toInt();
                    // 确保值不超过bit宽度的范围
                    int maxValue = (1 << bitWidth) - 1;
                    if (value > maxValue) {
                        qWarning() << "Value for bit field" << bitFieldName << "exceeds bit width of" << bitWidth << "bits";
                        value = maxValue;
                    } else if (value < 0) {
                        qWarning() << "Negative value for bit field" << bitFieldName << "not allowed";
                        value = 0;
                    }

                    // 设置位值
                    for (int i = 0; i < bitWidth; ++i) {
                        if (value & (1 << i)) {
                            byteValue |= (1 << (bitOffset + i));
                        }
                    }
                    paramUsed[bitFieldName] = true;
                } else {
                    qWarning() << "Missing required bit field parameter:" << bitFieldName;
                    return QByteArray();
                }
            }

            stream << byteValue;
        }
    }

    // 检查是否有未使用的参数
    for (auto it = params.begin(); it != params.end(); ++it) {
        if (!paramUsed.contains(it.key())) {
            qWarning() << "Unused parameter:" << it.key();
        }
    }

    return protocol;
}

/**
 * @brief 将值写入数据流
 * @param stream 目标数据流
 * @param value 要写入的值
 * @param length 数据长度
 */
void BinaryProtocolGenerator::writeValueToStream(QDataStream &stream, const QVariant &value, int length)
{
    if (value.type() == QVariant::Int || value.type() == QVariant::UInt) {
        quint64 intValue = value.toULongLong();
        if (length == 1) stream << static_cast<quint8>(intValue);
        else if (length == 2) stream << static_cast<quint16>(intValue);
        else if (length == 4) stream << static_cast<quint32>(intValue);
        else if (length == 8) stream << intValue;
        else stream << intValue; // 默认使用8字节
    } else if (value.type() == QVariant::Double) {
        double doubleValue = value.toDouble();
        if (length == 4) stream << static_cast<float>(doubleValue);
        else if (length == 8) stream << doubleValue;
        else stream << doubleValue; // 默认使用8字节
    } else if (value.type() == QVariant::String) {
        QString strValue = value.toString();
        // 截断或填充字符串到指定长度
        if (strValue.length() > length) {
            strValue = strValue.left(length);
        } else if (strValue.length() < length) {
            strValue = strValue.leftJustified(length, '\0', true);
        }
        stream.writeRawData(strValue.toUtf8().constData(), length);
    } else if (value.type() == QVariant::ByteArray) {
        QByteArray byteValue = value.toByteArray();
        // 截断或填充字节数组到指定长度
        if (byteValue.length() > length) {
            byteValue = byteValue.left(length);
        } else if (byteValue.length() < length) {
            byteValue = byteValue.leftJustified(length, '\0', true);
        }
        stream.writeRawData(byteValue.constData(), length);
    } else {
        // 未知类型，默认按字符串处理
        QString strValue = value.toString();
        if (strValue.length() > length) {
            strValue = strValue.left(length);
        } else if (strValue.length() < length) {
            strValue = strValue.leftJustified(length, '\0', true);
        }
        stream.writeRawData(strValue.toUtf8().constData(), length);
    }
}

/**
 * @brief 计算校验和
 * @param data 要计算校验和的数据
 * @param checksumType 校验和类型 (0: 求和校验, 1: CRC16, 2: 位级别异或)
 * @return 计算得到的校验和
 */
quint16 BinaryProtocolGenerator::calculateChecksum(const QByteArray &data, int checksumType)
{
    if (checksumType == 1) {
        // CRC16 校验
        quint16 crc = 0xFFFF;
        for (char c : data) {
            crc ^= static_cast<quint8>(c);
            for (int i = 0; i < 8; ++i) {
                if (crc & 1) {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        return crc;
    } else if (checksumType == 2) {
        // 位级别校验 (示例: 按位异或)
        quint16 checksum = 0;
        for (char c : data) {
            quint8 byte = static_cast<quint8>(c);
            for (int i = 0; i < 8; ++i) {
                checksum ^= ((byte >> i) & 1) << i;
            }
        }
        return checksum;

    } else {
        // 求和校验
        quint16 checksum = 0;
        for (char c : data) {
            checksum += static_cast<quint8>(c);
        }
        return checksum;
    }
}
